package server.service;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

/**
 *  通道处理器
 */
public class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
    //初始化channel
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        /**
         *  此处 添加Handler  可以想象成 一个个过滤器, 对数据的一步步操作, 可以自定义Handler 也可以添加netty提供的一些 handler,
         *  处理顺序   将根据 Inbound 添加的位置顺序 遍历执行,  如果是   outbound 则逆序执行  所以此时应该要注意添加的顺序
         */
        /**
         * addFirst(...)   //添加ChannelHandler在ChannelPipeline的第一个位置
         * addBefore(...)   //在ChannelPipeline中指定的ChannelHandler名称之前添加ChannelHandler
         * addAfter(...)   //在ChannelPipeline中指定的ChannelHandler名称之后添加ChannelHandler
         * addLast(...)   //在ChannelPipeline的末尾添加ChannelHandler
         * remove(...)   //删除ChannelPipeline中指定的ChannelHandler
         * replace(...)   //替换ChannelPipeline中指定的ChannelHandler
         */
        // todo 责任链模式  按顺序处理
        ChannelPipeline pipeline = socketChannel.pipeline();
        //字符串编码器
//        pipeline.addLast("stringEncodeHandler", new StringEncoder(CharsetUtil.UTF_8));
        //字符串解码器
//        pipeline.addLast("stringDecodeHandler", new StringDecoder(CharsetUtil.UTF_8));

        /**用于心跳检测  (空闲检测)
         * readerIdleTime:5  5秒没有读
         * writerIdleTime:6 6秒没有写
         * allIdleTime: 10  10秒没有读和写操作
         * timeUnit.SECONDS : 时间单位
         */
        pipeline.addLast(new IdleStateHandler(5,6,10, TimeUnit.SECONDS));


        //ChannelPipeline 可以动态添加ChannelHandler, 此处是 指定名称,从末尾添加
        pipeline.addLast("custeomHandler1", new TimeServerHandler());
    }

    /**
     *  当 ChannelPipeline 执行抛出异常时会调用此方法
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
    }

    /**
     *当 ChannelHandler 添加到 ChannelPipeline 调用
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        //可以看源码,  会将  ChannelHandlerContext  存储到一个Set<> 集合中,
        //Set<ChannelHandlerContext> initMap = Collections.newSetFromMap(new ConcurrentHashMap<ChannelHandlerContext, Boolean>());
        super.handlerAdded(ctx);
    }

    /**
     * 删除 Channel   当 ChannelHandler 从 ChannelPipeline 移除时调用
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        super.handlerRemoved(ctx);
    }


}
